package com.yfq.springframework.context.annotation;

import com.yfq.springframework.beans.annotation.AutowiredAnnotationBeanPostProcessor;
import com.yfq.springframework.beans.config.BeanDefinition;
import com.yfq.springframework.beans.support.BeanDefinitionRegistry;
import com.yfq.springframework.stereotype.Component;
import com.yfq.springframework.util.StringUtils;

import java.util.Set;

/**
 * @author 姚凤桥
 * @date 2023/2/4 21:15
 * @description
 */
public class ClasspathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
    private final BeanDefinitionRegistry registry;

    public ClasspathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        this.registry = registry;
    }

    public void doScan(String... basePackages) {
        for (String basePackage : basePackages) {
            Set<BeanDefinition> beanDefinitions = findCandidateComponents(basePackage);
            for (BeanDefinition beanDefinition : beanDefinitions) {
                beanDefinition.setScope(resolverBeanScope(beanDefinition));

                registry.registerBeanDefinition(determineBeanName(beanDefinition), beanDefinition);
            }
        }

        //扫描完包后手动注册AutowiredAnnotationBeanPostProcessor
        registry.registerBeanDefinition("autowiredAnnotationBeanPostProcessor", new BeanDefinition(AutowiredAnnotationBeanPostProcessor.class));
    }

    /**
     * 确定beanName
     */
    public String determineBeanName(BeanDefinition beanDefinition) {
        Class<?> clazz = beanDefinition.getBeanClass();
        if (clazz.isAnnotationPresent(Component.class)) {
            Component component = clazz.getAnnotation(Component.class);
            String value = component.value();
            if (!StringUtils.isEmpty(value)) {
                return value;
            }
        }

        return StringUtils.lowerFirst(clazz.getSimpleName());
    }

    /**
     * 解析bean的作用域
     */
    public String resolverBeanScope(BeanDefinition beanDefinition) {
        Class<?> clazz = beanDefinition.getBeanClass();
        if (clazz.isAnnotationPresent(Scope.class)) {
            Scope scope = clazz.getAnnotation(Scope.class);
            String value = scope.value();
            if (!StringUtils.isEmpty(value)) {
                return value;
            }
        }

        return "singleton";
    }

}
